/*
 * ParsingUtils.cpp
 *
 *  Created on: Nov 1, 2011
 *      Author: shaohong
 */

#include "ParsingUtils.h"
#include <iostream>
#include <sstream>
#include <cstddef>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <utility>

#include "NmpsException.h"

using namespace std;

namespace nmps {

ParsingUtils::ParsingUtils() {
}

ParsingUtils::~ParsingUtils() {
}



void ParsingUtils::sipGetLine(istream& inputStream, string &lineStr) {
	char newChar=0;

	lineStr.clear();
	if (inputStream.eof()) {
		return;
	}

	newChar = inputStream.get();

	while (newChar != '\x0d') {
		lineStr.append(1, newChar);
		if (!inputStream.eof()) {
			newChar = inputStream.get();
		} else {
			break;
		}
	}

	if (!inputStream.eof()) {
		newChar = inputStream.get();
		if (newChar != '\x0a') {
//			fprintf(stderr, "%c\n", newChar);
			throw NmpsException("sipGetLine meet Invalid SIP line");
		}

	}

	return;

}

bool ParsingUtils::isEmptyLine(string &aLine){
	string::iterator itr = aLine.begin();
	while (itr != aLine.end()){
		if (isprint(*itr))
			return false;
		itr++;
	}

	return true;
}
/**
 * Given an HTML page, extract the playlist URIs contained in this HTML page
 * The ones like this: http://yp.shoutcast.com/sbin/tunein-station.pls?id=1926281
 *
 */
void ParsingUtils::extractPlayListURI(char * htmlPage,
		list<RadioChannel>& radioChannelList) {
	int maxChannelNumber = 10;

	string htmlPageStr = string(htmlPage);
	stringstream ss(htmlPageStr, ios_base::in);
	string currLine;

	int counter = 1;

	while (!ss.eof()) {
		getline(ss, currLine);

		// an interesting line looks like this:
//		   <a href="http://yp.shoutcast.com/sbin/tunein-station.pls?id=179361" title="89.3 KPCC - Southern California Public Radio" class="playbutton playimage" name="89.3 KPCC - Southern California Public Radio" id="179361"></a>
//		<a class="playbutton playimage" id="1377200" name="TechnoBase.FM - 24h Techno, Dance, Tranc..." href="http://yp.shoutcast.com/sbin/tunein-station.pls?id=1377200"></a>

		if (string::npos != currLine.find("href=\"http:")
				&& string::npos != currLine.find("class=\"playbutton playimage")
				&& string::npos != currLine.find("name=")
				&& string::npos != currLine.find("id=")){

//			cerr << "\n *** This line is interesting:\n" << currLine << endl;
			// This is the line we're interested in.
			size_t addressStartPos = currLine.find("http://");
			size_t addressEndPos = currLine.find('"', addressStartPos);
			string address = currLine.substr(addressStartPos, addressEndPos - addressStartPos);
//			cerr << "address = " << address << endl;

			string nameKeyWord = "name=\"";
			size_t nameStartPos = currLine.find(nameKeyWord) + nameKeyWord.length();
			size_t nameEndPos = currLine.find('"', nameStartPos);
			string name = currLine.substr(nameStartPos, nameEndPos - nameStartPos);
//			cerr << "title = " << title << endl;

			string idKeyWord = "id=\"";
			size_t idStartPos = currLine.find(idKeyWord) + idKeyWord.length();
			size_t idEndPos = currLine.find('"', idStartPos);
			string id = currLine.substr(idStartPos, idEndPos - idStartPos);
//			cerr << "id = " << id << endl;

			RadioChannel * newChannel = new RadioChannel();
			newChannel->channelNumber = counter++;
			newChannel->channelID = id;
			newChannel->title = name;
			newChannel->playlistURL = address;

			radioChannelList.push_back((*newChannel));
			if (counter == maxChannelNumber) {
				return;
			}
		}
	}

}

//
//string ParsingUtils::getHostPartOfURL(char * playlistURI) {
//
//	// hard code it for now
//	return "yp.shoutcast.com";
//}
//
//string ParsingUtils::getPathFromURL(char * playlistURI) {
//	// hard code it for now
//	return "/sbin/tunein-station.pls?id=1926281";
//}
//

/*
 * Given an HTTP response, extract the PlayfileLocation.
 * e.g. for an HTTP response:
HTTP/1.1 200 OK
Date: Sun, 13 Nov 2011 19:07:57 GMT
Server: Apache-Coyote/1.1
Cache-Control: no-cache
Pragma: no-cache
Content-Type: audio/x-scpls;charset=ISO-8859-1
Content-Length: 111
Set-Cookie: JSESSIONID=29055A9C2C9390461706A4F9A576D1E8; Path=/yp
Keep-Alive: timeout=5, max=67
Connection: Keep-Alive

[playlist]
numberofentries=1
File1=http://69.166.45.47:8000
Title1=(#1 - 37/250) NPR News
Length1=-1
Version=2
 *
 * we want to return  http://69.166.45.47:8000
 */
string ParsingUtils::getPlayFileLocationFromHttpResponse(char * httpResponse) {
	string htmlPageStr = string(httpResponse);
	stringstream ss(htmlPageStr, ios_base::in);
	string currLine;

	while (!ss.eof()) {
		getline(ss, currLine);

		string file1Token = string("File1=");
		if (string::npos != currLine.find(file1Token)) {
			size_t file1StartPos = currLine.find(file1Token);
			return currLine.substr(file1StartPos + file1Token.length());
		}
	}

	return "";
}

void ParsingUtils::parseRecipientList(char * recipientlistData,
		list<pair<string, int> >& recipientList) {

//	// the recipientlist should be something like "ip:port[;more_ip:more_port]..."

	recipientList.clear();
	char * pch;
//	printf("Splitting string \"%s\" into tokens:\n", str);
	pch = strtok(recipientlistData, ",;");
	while (pch != NULL) {
//		fprintf(stderr, "%s\n", pch);
		string pairStr = string(pch);
		size_t columnPos = pairStr.find(':');
		string ipStr = pairStr.substr(0, columnPos);
		string portStr = pairStr.substr(columnPos+1);
		int port = atoi(portStr.c_str());
		recipientList.push_back(make_pair(ipStr, port));
		pch = strtok(NULL, ",;");
	}
}

/**
 * get the number of lines in this sipMessage
 */
int ParsingUtils::getNumberOfLines(string& sipMessage) {

	// I think this should be just like counting the number of '\n' in the message
	int ret = 0;

	stringstream ss(sipMessage, ios_base::in);

	string tmpStr;

	while (!ss.eof()) {
		ParsingUtils::sipGetLine(ss, tmpStr);
//		fprintf(stderr, "%s\n", tmpStr.c_str());
//		cout << tmpStr << endl;
		ret++;
	}

	return ret;
}

/**
 * here we assume the line passed in is a valid request line
 */
string ParsingUtils::extractMethod(string& currLine) {
	//INVITE sip:francisco@bestel.com:55060 SIP/2.0
	size_t spacePos = currLine.find(' ');
	if (string::npos == spacePos) {
		throw NmpsException("invalid request line " + currLine);
	}

	return currLine.substr(0, spacePos);

}

string ParsingUtils::extractRequestUri(string& currLine) {
	//INVITE sip:francisco@bestel.com:55060 SIP/2.0
	size_t spacePos = currLine.find(' ');
	if (string::npos == spacePos) {
		throw NmpsException("invalid request line " + currLine);
	}

	size_t requestUriStartPos = spacePos + 1;

	size_t requestUriEndPos = currLine.find(' ', requestUriStartPos);
	return currLine.substr(requestUriStartPos,
			requestUriEndPos - requestUriStartPos);
}

string ParsingUtils::extractHeaderName(string& currLine) {
	//	From: <sip:200.57.7.195:55061;user=phone>;tag=GR52RWG346-34"

	size_t columnPos = currLine.find(':');
	if (string::npos == columnPos) {
		fprintf(stderr, "currLine=%s\n", currLine.c_str());
		throw NmpsException(string("extractHeaderName invalid header line"));
	}


	string headerName = currLine.substr(0, columnPos);
//	fprintf(stderr, "headerName = \"%s\"\n", headerName.c_str());

	return headerName;
}

string ParsingUtils::extractHeaderValue(string& currLine) {
	//	From: <sip:200.57.7.195:55061;user=phone>;tag=GR52RWG346-34"

	size_t spacePos = currLine.find(' ');
	if (string::npos == spacePos) {
		fprintf(stderr, "currLine=%s\n", currLine.c_str());
		throw NmpsException(string("extractHeaderValue meet invalid header line "));
	}

	string headerValue = currLine.substr(spacePos + 1, (currLine.length() - spacePos));
//	fprintf(stderr, "headerValue = \"%s\"\n", headerValue.c_str());

	return headerValue;
}


int ParsingUtils::extractDTMFSignal(string & contentStr) {

	int ret = -1;
	stringstream ss(contentStr, ios_base::in);
	string currLine;

	while (!ss.eof()) {
		getline(ss, currLine);
		//The line looks like "Signal=2"
		string signalToken = "Signal=";
		size_t signalTokenPos = currLine.find(signalToken);
		if (string::npos == signalTokenPos) {
			continue;
		}
		string digitPart = currLine.substr(signalTokenPos+signalToken.length());
		return atoi(digitPart.c_str());
	}

	return ret;
}

} /* namespace nmps */
